#ifndef _UTILES_H
#define _UTILES_H

/*============================================================================
SeparaCadena()
============================================================================*/
void SeparaCadena(char *sParametro,char *sValor,char *cadena) {

   int		iConta1=0,iConta2=0;

   strcpy(sParametro,cadena);

   while(sParametro[iConta1]!='='){
         iConta1++;
	}

	sParametro[iConta1]='\0';
    iConta1++;
    while(cadena[iConta1]!='\n') {
        sValor[iConta2]=cadena[iConta1];
	    iConta1++;iConta2++;
	 }

    sValor[iConta2]='\0';
}

/*============================================================================
cargarConfiguracion()
Lee el archivo de configuracion y carga los datos a la estructura del PRAID
============================================================================*/

int cargarConfiguracion() {

	FILE		*pArch;
	char		sParam[100],sValor[100],Aux[100];

	memset(Aux,'\0',100);
	//TODO CAMBIAR EL PATH PARA LA PRUEBA FINAL O EN EL DE PRUEBAS, PONER: ../PPD/
	if ((pArch = fopen("../PPD/PPDconfig.txt", "r"))==NULL) {
		printf("no encontre el archivo configuracion\n");
		return 0;
	}//else
		//printf("encontre el arch configuracion\n");

	stPConsola.szPathPPD=(char *)malloc(sizeof(char)*250);
	while (!feof(pArch)) {
		fgets(Aux,100,pArch);
		SeparaCadena(sParam,sValor,Aux);

		if(strcmp(sParam,"PATHCONSOLA")==0)
			strcpy(stPConsola.szPathPPD,sValor);
		else if(strcmp(sParam,"C")==0)
			stPConsola.iCilindro = atoi(sValor);
		else if(strcmp(sParam,"H")==0)
			stPConsola.iHead = atoi(sValor);
		else if(strcmp(sParam,"S")==0)
			stPConsola.iSector = atoi(sValor);
		else if(strcmp(sParam,"TLECTURA")==0)
			stPConsola.iTiempoLectura = atoi(sValor);
		else if(strcmp(sParam,"TESCRITURA")==0)
			stPConsola.iTiempoEscritura = atoi(sValor);
		else if(strcmp(sParam,"RPM")==0)
			stPConsola.iRPM = atoi(sValor);
		else if(strcmp(sParam,"TSALTO")==0)
			stPConsola.iTiempoSalto = atoi(sValor);
		else if(strcmp(sParam,"ID")==0)
			strcpy(stPConsola.szIdPPD,sValor);

		//printf("Valor: %s\n", sValor);
	}
	fclose(pArch);
	return 1;
}

/*============================================================================
iniciarLog()
Abre el archivo log y escribe el encabezado. Recibe como parametros:
- *nombreLog: nombre del archivo log a crearse.
============================================================================*/
void iniciarLog( const char *nombreLog )
{
	FILE		*pArchLog;
	time_t		tiempo;
	struct tm	*ptm;

	time(&tiempo);
	ptm = localtime(&tiempo );

	pArchLog = fopen(nombreLog,"a");

	fprintf(pArchLog, "Fecha\t  NombreProceso\t[PIDproceso]  [ThreadID]:TipoLog Dato\n");
	fprintf(pArchLog, "************************************************************\n");

	fclose(pArchLog);

}

/*============================================================================
log()
Abre el archivo log y escribe al final. Recibe como parametros:
- *nombreLog: nombre del archivo log.
- *name: puntero al nombre del proceso.
- *type: tipo de mensaje (ERROR, INFO, etc).
- *log: puntero a la cadena, que contiene el mensaje a escribir en el archivo.
============================================================================*/
void log( const char *nombreLog, const char *name, const char *type, const char *log)
{
	FILE		*pArchLog;
	time_t		tiempo;
	struct tm	*ptm;
	time(&tiempo);

	ptm = gmtime(&tiempo );

	pArchLog = fopen(nombreLog,"a");

	fprintf(pArchLog, "[%2d:%02d:%02d]  [%s]\t[%d]\t\t[%d]\t[%s]\t[%s]\n",ptm->tm_hour, ptm->tm_min, ptm->tm_sec, name, getpid(), pthread_self(), type, log);
/*%2d:%02d:%04d - ptm->tm_mday, ptm->tm_mon+1, ptm->tm_year+1900, */
	fclose(pArchLog);

}

/*============================================================================
generarSocketEscucha()
Funcion que genera el socket por el que escuchara el proceso.
============================================================================*/
/*int generarSocketEscucha ()	{

	int					iSocket, iYes, iRta;
	int					iBacklog=25;
	struct sockaddr_in	stDireccion;

	if((iSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		log( "ppdLog.txt", "PPD", "ERROR", "Al generar el socket de escucha");
		return -1;
	} else {

    if(setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iYes, sizeof(int)) == -1) {
    	log( "ppdLog.txt", "PPD", "ERROR", "Al generar el socket de escucha");
    	return -1;
	}}

	if( stPPD.szIpPPD == NULL ){
		stDireccion.sin_addr.s_addr = inet_addr(stPPD.szIpPPD);
	  } else {
		stDireccion.sin_addr.s_addr = inet_addr(stPPD.szIpPPD);
	  }

	  stDireccion.sin_family = AF_INET;		 /* host byte order*/
	  /*stDireccion.sin_port = htons( stPPD.iPuertoPPD );	 /* short, network byte order*/
/*memset( &(stDireccion.sin_zero), '\0', 8 );	/* rellena con ceros el resto de la estructura*/

	/*Se establece el socket para escucha (struct sockaddr *) */
/*if( bind(iSocket, (struct sockaddr *)&stDireccion, sizeof(struct sockaddr)) == -1 ) {
		log( "ppdLog.txt", "PPD", "ERROR", "Al generar el socket de escucha");
		return -1;
	  } else {

     if( listen( iSocket, iBacklog ) == -1 ) { /*Establezco el socket para esperar conexiones*/
/*  	 log( "ppdLog.txt", "PPD", "ERROR", "Al generar el socket de escucha");
		 return -1;
	 }  }

return iSocket;
}

int atiendeNuevaConexion( void ) {
	int 				iNuevoSock;
	ST_NIPC				stCabecera;
	struct sockaddr_in	stDirNuevaCnx;	/* Informacion de la direccion de una nueva conexion*/
/*	socklen_t			sin_size;

	sin_size = sizeof(struct sockaddr_in); /*Tamaño de la estructura sockaddr_in*/
/*	memset( &stDirNuevaCnx, '\0', sin_size ); /*Inicializo la estructura*/

/*	if( (iNuevoSock = accept( stPPD.iSocketEscucha, (struct sockaddr *) &stDirNuevaCnx, &sin_size )) == -1) {
		log( "ppdLog.txt", "PPD", "ERROR", "Al aceptar nueva conexion");
		printf("error en accept");
		return -1;
	}

	if( recv( iNuevoSock, (void *) &stCabecera, sizeof(ST_NIPC), 0) < 0 ) {
		close( iNuevoSock );
		log( "ppdLog.txt", "PFD", "ERROR","Al recibir Mensaje de nueva conexion");
		return -4;
	}

	if(stCabecera.ucType == HANDSHAKE) {
		stCabecera.ucType = PPD;
		stCabecera.lPayload = 0;

		if( send( iNuevoSock, &stCabecera, sizeof(ST_NIPC), 0 ) < 0 ){
			close( iNuevoSock );
			log( "ppdLog.txt", "PPD", "ERROR","Al enviar respuesta Hand Shake");
			return -3;
		}else
			log( "ppdLog.txt", "PPD", "INFO", "Se conectó con el PFS");
		/* EN CASO DE ERROR CARGAR stCabecera.ucType CON FAIL Y ENVIAR */
/*	}
/* VERIFICAR SI ES NECESARIO GUARDAR iNuevoSock YA QUE SIEMPRE SE TRATARA DEL PFS, ESTE SE PODRA CONECTAR MAS DE UNA VEZ*/
/*	return 0;
}

int CreaSocketPraid(char * ip, char * puerto)
{
	int sockfd;
    struct sockaddr_in their_addr;
	int port;

	port=atoi(puerto);

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket");
        exit(1);
    }

    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(port);
    their_addr.sin_addr.s_addr = inet_addr(ip);
    memset(&(their_addr.sin_zero),'\0', 8);
	printf("Prueba Enviar\n");
    if (connect(sockfd, (struct sockaddr *)&their_addr,sizeof(their_addr)) == -1) {
        printf("connect");
        exit(1);
    }

	return sockfd;
}

/*============================================================================
leerBootSector_mmap()
============================================================================*/
/*int leerSector( ST_SECTOR *buffer, int sector_leer, int sector_actual )
{
	if (lseek(stPPD.ArchivoEnDisco, sector_actual, sector_leer) > 0)
		memcpy(buffer, stPPD.ArchivoEnDisco, sizeof(ST_SECTOR));

	return 1;
}*/

int32_t CHStoLBA(int cilindro, int cabeza, int sector)
{
	//LBA = ( (cylinder * heads_per_cylinder + heads ) * sectors_per_track ) + sector - 1
	return (int32_t)(((cilindro * stPConsola.iCilindro + cabeza ) * stPConsola.iSector ) + sector - 1);
}

ST_CHS LBAtoCHS(int32_t sectorBuscado)
{
	int 	temporal;
	ST_CHS 	stCHS;

	stCHS.cilindro = sectorBuscado / (stPConsola.iHead * stPConsola.iSector);
	temporal = sectorBuscado % (stPConsola.iCilindro * stPConsola.iSector);
	stCHS.cabeza = temporal / stPConsola.iSector;
	stCHS.sector = (sectorBuscado % stPConsola.iSector) ;

	/*  cylinder = LBA / (heads_per_cylinder * sectors_per_track)
		temp = LBA % (heads_per_cylinder * sectors_per_track)
		head = temp / sectors_per_track
		sector = temp % sectors_per_track + 1
	*/
	return stCHS;
}

int imprimoTrazo(int32_t sectorActual, int32_t sectorPedido, int32_t sectorProximo )
{
	ST_CHS	chsActual, chsPedido, chsSiguiente;
	char trazo[250000];
	char t[25];
	int i=0, cantPistas=0, cantSectores=0;
	int tiempo=0;
	int32_t sectorSiguiente;

	chsActual = LBAtoCHS(sectorActual);
	chsPedido = LBAtoCHS(sectorPedido);

	printf("\nPosicion Actual: %d:%d\n", chsActual.cilindro, chsActual.sector);
	printf("Posicion Solicitado: %d:%d\n", chsPedido.cilindro, chsPedido.sector);

	strcpy(trazo, "");
	strcpy(t, "");

	//sprintf(t, " %d:%d ", chsActual.cilindro, chsActual.sector );
	//strcat(trazo, t);

	if(chsActual.cilindro < chsPedido.cilindro)
	{
		for(i=chsActual.cilindro; i < chsPedido.cilindro; i++)
		{
			sprintf(t, " %d:%d ", i, chsActual.sector );
			strcat(trazo, t);
			cantPistas++;
		}
		chsActual.cilindro = i;
	}
	else if(chsActual.cilindro > chsPedido.cilindro)
	{
		for(i=chsActual.cilindro; i > chsPedido.cilindro; i--)
		{
			sprintf(t, " %d:%d ", i, chsActual.sector );
			strcat(trazo, t);
			cantPistas++;
		}
		chsActual.cilindro = i;
	}


	if(chsActual.sector < chsPedido.sector)
	{
		for(i=chsActual.sector; i < chsPedido.sector; i++)
		{
			sprintf(t, " %d:%d ", chsActual.cilindro, i );
			strcat(trazo, t);
			cantSectores++;
		}
		chsActual.sector = i;
		sectorSiguiente = chsPedido.sector+1;
	}
	else if(chsActual.sector > chsPedido.sector)
	{
		for(i=chsActual.sector; i > chsPedido.sector; i--)
		{
			sprintf(t, " %d:%d ", chsActual.cilindro, i );
			strcat(trazo, t);
			cantSectores++;
		}
		chsActual.sector = i;
		sectorSiguiente = chsPedido.sector-1;
	}

	sprintf(t, " %d:%d ", chsPedido.cilindro, chsPedido.sector );
	strcat(trazo, t);

	printf("Sectores recorridos: %s\n", trazo);

	//printf("Cant Sectores: %d \n", cantSectores);
	//printf("T. entre sectores: %d ms \n", stPConsola.tiempoEntreSectores);

	tiempo=(cantSectores*stPConsola.tiempoEntreSectores)+(cantPistas*stPConsola.iTiempoSalto);
	printf("Tiempo Consumido: %d ms \n", tiempo);

	if (sectorProximo > -1)
	{
		chsSiguiente = LBAtoCHS(sectorProximo);
		printf("Proximo Sector: %d:%d \n", chsSiguiente.cilindro, chsSiguiente.sector);
	}else
		printf("Proximo Sector: ... \n");

	return 0;
}

#endif
